package org.lhg.simple;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * bean工厂类
 *
 * @author lhg
 */
public class BeanFactory {
    /**
     * 用于存储bean的单例实体
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
    /**
     * 用于存储beanDefinition
     */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    /**
     * 注册beanDefinition
     */
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        beanDefinitionMap.put(beanName, beanDefinition);
    }

    /**
     * 获取bean 如果不存在则创建
     */
    public Object getBean(String beanName) {
        Object bean = getSingleton(beanName);
        if (bean == null) {
            bean = doCreateBean(beanDefinitionMap.get(beanName));
            singletonObjects.put(beanName, bean);
        }
        return bean;
    }

    public Object getSingleton(String beanName) {
        return this.singletonObjects.get(beanName);
    }


    private Object doCreateBean(final BeanDefinition beanDefinition) {
        Object bean = createBeanInstance(beanDefinition);
        applyPropertyValues(bean, beanDefinition);
        return bean;
    }

    private Object createBeanInstance(BeanDefinition beanDefinition) {
        Object bean = new Object();
        try {
            bean = beanDefinition.getBeanClass().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return bean;
    }

    private void applyPropertyValues(Object bean, BeanDefinition beanDefinition) {
        PropertyValues pvs = beanDefinition.getPropertyValues();
        if (pvs != null) {
            try {
                for (PropertyValue pv : pvs.getPropertyValueList()) {
                    Field field = bean.getClass().getDeclaredField(pv.getName());
                    field.setAccessible(true);
                    field.set(bean,pv.getValue());
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

}
